<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ZWiki WebSocket 实时通知测试</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 50px rgba(0,0,0,0.3);
            overflow: hidden;
        }

        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }

        .header h1 {
            font-size: 32px;
            margin-bottom: 10px;
        }

        .status-bar {
            display: flex;
            justify-content: space-around;
            padding: 20px;
            background: #f8f9fa;
            border-bottom: 1px solid #dee2e6;
        }

        .status-item {
            text-align: center;
        }

        .status-label {
            font-size: 14px;
            color: #6c757d;
            margin-bottom: 5px;
        }

        .status-value {
            font-size: 24px;
            font-weight: bold;
        }

        .status-value.online {
            color: #28a745;
        }

        .status-value.offline {
            color: #dc3545;
        }

        .controls {
            padding: 20px;
            background: #fff;
            border-bottom: 1px solid #dee2e6;
        }

        .control-group {
            margin-bottom: 15px;
        }

        .control-group label {
            display: block;
            margin-bottom: 5px;
            font-weight: 600;
            color: #495057;
        }

        .control-group input {
            width: 200px;
            padding: 8px 12px;
            border: 1px solid #ced4da;
            border-radius: 4px;
            font-size: 14px;
        }

        button {
            padding: 10px 20px;
            margin-right: 10px;
            background: #667eea;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s;
        }

        button:hover {
            background: #764ba2;
            transform: translateY(-2px);
        }

        button:active {
            transform: translateY(0);
        }

        button.danger {
            background: #dc3545;
        }

        button.danger:hover {
            background: #c82333;
        }

        .messages {
            padding: 20px;
            max-height: 500px;
            overflow-y: auto;
        }

        .message-item {
            padding: 15px;
            margin-bottom: 10px;
            border-radius: 8px;
            border-left: 4px solid #667eea;
            background: #f8f9fa;
            animation: slideIn 0.3s ease-out;
        }

        @keyframes slideIn {
            from {
                opacity: 0;
                transform: translateX(-20px);
            }
            to {
                opacity: 1;
                transform: translateX(0);
            }
        }

        .message-type {
            font-weight: bold;
            color: #667eea;
            margin-bottom: 5px;
        }

        .message-content {
            color: #495057;
            margin-bottom: 5px;
        }

        .message-time {
            font-size: 12px;
            color: #6c757d;
        }

        .message-item.welcome {
            border-left-color: #28a745;
        }

        .message-item.queued {
            border-left-color: #17a2b8;
        }

        .message-item.started {
            border-left-color: #ffc107;
        }

        .message-item.progress {
            border-left-color: #007bff;
        }

        .message-item.completed {
            border-left-color: #28a745;
        }

        .message-item.failed {
            border-left-color: #dc3545;
        }

        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: #6c757d;
        }

        .empty-state svg {
            width: 100px;
            height: 100px;
            margin-bottom: 20px;
            opacity: 0.5;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🚀 ZWiki WebSocket 实时通知测试</h1>
            <p>实时推送 · 毫秒级延迟 · 双向通信</p>
        </div>

        <div class="status-bar">
            <div class="status-item">
                <div class="status-label">连接状态</div>
                <div id="connection-status" class="status-value offline">未连接</div>
            </div>
            <div class="status-item">
                <div class="status-label">接收消息</div>
                <div id="message-count" class="status-value">0</div>
            </div>
            <div class="status-item">
                <div class="status-label">在线用户</div>
                <div id="online-count" class="status-value">-</div>
            </div>
        </div>

        <div class="controls">
            <div class="control-group">
                <label for="user-id">用户ID:</label>
                <input type="number" id="user-id" value="123" />
            </div>

            <button onclick="connect()">🔌 连接</button>
            <button onclick="disconnect()" class="danger">🔌 断开</button>
            <button onclick="sendPing()">💓 心跳</button>
            <button onclick="subscribeTask()">📝 订阅任务</button>
            <button onclick="clearMessages()">🗑️ 清空消息</button>
        </div>

        <div class="messages" id="messages">
            <div class="empty-state">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
                </svg>
                <p>暂无消息，请先连接WebSocket</p>
            </div>
        </div>
    </div>

    <script>
        let ws = null;
        let messageCount = 0;

        // 连接WebSocket
        function connect() {
            const userId = document.getElementById('user-id').value;
            if (!userId) {
                alert('请输入用户ID');
                return;
            }

            if (ws && ws.readyState === WebSocket.OPEN) {
                alert('已经连接，请勿重复连接');
                return;
            }

            const wsUrl = `ws://localhost:8096/zwiki-service/ws/notification/${userId}`;
            console.log('正在连接:', wsUrl);

            ws = new WebSocket(wsUrl);

            ws.onopen = (event) => {
                console.log('✅ WebSocket连接成功', event);
                updateConnectionStatus(true);
                addMessage('system', '✅ 连接成功', 'WebSocket连接已建立');
            };

            ws.onmessage = (event) => {
                console.log('📨 收到消息:', event.data);
                const data = JSON.parse(event.data);
                handleMessage(data);
            };

            ws.onclose = (event) => {
                console.log('❌ WebSocket连接关闭', event);
                updateConnectionStatus(false);
                addMessage('system', '❌ 连接关闭', `状态码: ${event.code}`);
            };

            ws.onerror = (error) => {
                console.error('⚠️ WebSocket错误', error);
                addMessage('error', '⚠️ 连接错误', error.toString());
            };
        }

        // 断开连接
        function disconnect() {
            if (ws) {
                ws.close();
                ws = null;
            }
        }

        // 发送心跳
        function sendPing() {
            if (ws && ws.readyState === WebSocket.OPEN) {
                ws.send('ping');
                addMessage('send', '💓 发送心跳', 'ping');
            } else {
                alert('WebSocket未连接');
            }
        }

        // 订阅任务
        function subscribeTask() {
            if (ws && ws.readyState === WebSocket.OPEN) {
                const taskId = prompt('请输入要订阅的任务ID:');
                if (taskId) {
                    ws.send(`subscribe:${taskId}`);
                    addMessage('send', '📝 订阅任务', `任务ID: ${taskId}`);
                }
            } else {
                alert('WebSocket未连接');
            }
        }

        // 处理接收到的消息
        function handleMessage(data) {
            messageCount++;
            updateMessageCount();

            let cssClass = '';
            let icon = '📨';

            switch(data.type) {
                case 'welcome':
                    cssClass = 'welcome';
                    icon = '👋';
                    break;
                case 'TASK_QUEUED':
                    cssClass = 'queued';
                    icon = '📋';
                    break;
                case 'TASK_STARTED':
                    cssClass = 'started';
                    icon = '🚀';
                    break;
                case 'TASK_PROGRESS':
                    cssClass = 'progress';
                    icon = '📊';
                    break;
                case 'TASK_COMPLETED':
                    cssClass = 'completed';
                    icon = '🎉';
                    break;
                case 'TASK_FAILED':
                    cssClass = 'failed';
                    icon = '❌';
                    break;
                case 'subscribed':
                    cssClass = 'system';
                    icon = '✅';
                    break;
                default:
                    cssClass = 'default';
            }

            const message = data.message || JSON.stringify(data, null, 2);
            addMessage(cssClass, `${icon} ${data.type}`, message, data);
        }

        // 添加消息到列表
        function addMessage(type, title, content, rawData) {
            const messagesDiv = document.getElementById('messages');
            
            // 移除空状态
            const emptyState = messagesDiv.querySelector('.empty-state');
            if (emptyState) {
                emptyState.remove();
            }

            // 创建消息元素
            const messageDiv = document.createElement('div');
            messageDiv.className = `message-item ${type}`;
            
            const typeDiv = document.createElement('div');
            typeDiv.className = 'message-type';
            typeDiv.textContent = title;
            
            const contentDiv = document.createElement('div');
            contentDiv.className = 'message-content';
            contentDiv.textContent = content;
            
            const timeDiv = document.createElement('div');
            timeDiv.className = 'message-time';
            timeDiv.textContent = new Date().toLocaleTimeString('zh-CN');
            
            messageDiv.appendChild(typeDiv);
            messageDiv.appendChild(contentDiv);
            messageDiv.appendChild(timeDiv);

            // 如果有原始数据，添加详情按钮
            if (rawData) {
                const detailBtn = document.createElement('button');
                detailBtn.textContent = '查看详情';
                detailBtn.style.marginTop = '10px';
                detailBtn.style.fontSize = '12px';
                detailBtn.onclick = () => {
                    alert(JSON.stringify(rawData, null, 2));
                };
                messageDiv.appendChild(detailBtn);
            }
            
            // 插入到顶部
            messagesDiv.insertBefore(messageDiv, messagesDiv.firstChild);

            // 限制消息数量
            if (messagesDiv.children.length > 50) {
                messagesDiv.removeChild(messagesDiv.lastChild);
            }
        }

        // 更新连接状态
        function updateConnectionStatus(connected) {
            const statusEl = document.getElementById('connection-status');
            if (connected) {
                statusEl.textContent = '已连接';
                statusEl.className = 'status-value online';
            } else {
                statusEl.textContent = '未连接';
                statusEl.className = 'status-value offline';
            }
        }

        // 更新消息计数
        function updateMessageCount() {
            document.getElementById('message-count').textContent = messageCount;
        }

        // 清空消息
        function clearMessages() {
            messageCount = 0;
            updateMessageCount();
            
            const messagesDiv = document.getElementById('messages');
            messagesDiv.innerHTML = `
                <div class="empty-state">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
                    </svg>
                    <p>暂无消息</p>
                </div>
            `;
        }

        // 定期查询在线用户数
        setInterval(() => {
            fetch('/api/v1/websocket/online-count')
                .then(res => res.json())
                .then(data => {
                    if (data.code === '0') {
                        document.getElementById('online-count').textContent = data.data.onlineCount;
                    }
                })
                .catch(err => {
                    console.error('查询在线用户数失败', err);
                });
        }, 5000);

        // 页面加载时自动连接
        window.onload = () => {
            // 可以自动连接
            // connect();
        };
    </script>
</body>
</html>

